home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / Pascal / Applications / NIH Image 1.62b11 / Macros / Stacks < prev    next >
Text File  |  1997-04-11  |  13KB  |  638 lines

  1. {This file contains macros that work with stacks.}
  2.  
  3. procedure CheckForStack;
  4. begin
  5.   if nPics=0 then begin
  6.     PutMessage('This macro requires a stack.');
  7.     exit;
  8.   end;
  9.   if nSlices=0 then begin
  10.     PutMessage('This window is not a stack.');
  11.     exit
  12.   end;
  13. end;
  14.  
  15.  
  16. macro 'Add Slice [A]';    begin CheckForStack; AddSlice end;
  17. macro 'Delete Slice [D]'; begin CheckForStack; DeleteSlice end;
  18. macro 'First Slice [F]';  begin CheckForStack; SelectSlice(1) end;
  19. macro 'Last Slice [L]';   begin CheckForStack; SelectSlice(nSlices) end;
  20.  
  21. macro 'Select Slice… [S]';
  22. var
  23.   n:integer;
  24. begin
  25.  CheckForStack;
  26.  n:=GetNumber('Slice Number:',trunc(nSlices/2));
  27.  SelectSlice(n)
  28. end;
  29.  
  30.  
  31. macro '(-' begin end;
  32.  
  33. macro 'Smooth';
  34. var
  35.   i:integer;
  36. begin
  37.   CheckForStack;
  38.   for i:= 1 to nSlices do begin
  39.     SelectSlice(i);
  40.     SetOption; Smooth;
  41.   end;
  42. end;
  43.  
  44.  
  45. macro 'Sharpen';
  46. var
  47.   i:integer;
  48. begin
  49.   CheckForStack;
  50.   for i:= 1 to nSlices do begin
  51.     SelectSlice(i);
  52.     SetOption; Smooth;
  53.     SetOption; Sharpen;
  54.   end;
  55. end;
  56.  
  57.  
  58. macro 'Reduce Noise';
  59. var
  60.   i:integer;
  61. begin
  62.   CheckForStack;
  63.   for i:= 1 to nSlices do begin
  64.     SelectSlice(i);
  65.     ReduceNoise;
  66.   end;
  67. end;
  68.  
  69.  
  70. macro 'Apply LUT';
  71. var
  72.   i,stack,slices:integer;
  73. begin
  74.   CheckForStack;
  75.   stack:=PicNumber;
  76.   slices:=nSlices;
  77.   Duplicate('Temp');
  78.   for i:= 1 to slices do begin
  79.     SelectPic(stack);
  80.     SelectSlice(i);
  81.     ApplyLut;
  82.     SelectPic(nPics);
  83.     if i<>slices then PropagateLut;
  84.   end;
  85.   SelectPic(nPics);
  86.   Dispose;
  87. end;
  88.  
  89.  
  90. macro 'Fix Colors';
  91. {
  92. Changes 0 to 1 and 255 to 254 in all slices. We want to do this because
  93. pixel values of 0(which always displays as white) and 255(always
  94. displays as black) cause problems when pseudo-coloring images.
  95. }
  96. var
  97.   i:integer;
  98. begin
  99.   CheckForStack;
  100.   for i:= 1 to nSlices do begin
  101.     SelectSlice(i);
  102.     ChangeValues(0,0,1);
  103.     ChangeValues(255,255,254);
  104.   end;
  105. end;
  106.  
  107. macro 'Subtract Background…';
  108. var
  109.   radius,i:integer;
  110. begin
  111.   CheckForStack;
  112.   radius:=GetNumber('Rolling ball radius (pixels):',50);
  113.   for i:= 1 to nSlices do begin
  114.     SelectSlice(i);
  115.     SubtractBackground('2D Rolling Ball',radius);
  116.   end;
  117. end;
  118.  
  119.  
  120. macro '(-' begin end;
  121.  
  122.  
  123. procedure CheckForSelection;
  124. var 
  125.   x1,y1,x2,y2,LineWidth:integer;
  126. begin
  127.   GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight);
  128.   GetLine(x1,y1,x2,y2,LineWidth);
  129.   if (RoiWidth=0) or (x1>=0) then begin
  130.     PutMessage('Please make a rectangular selection.');
  131.     exit;
  132.   end;
  133. end;
  134.  
  135.  
  136. procedure CropAndScale(fast:boolean; angle:real);
  137. var
  138.   i,OldStack,NewStack:integer;
  139.   RoiLeft,RoiTop,RoiWidth,RoiHeight:integer;
  140.   N,NewWidth:integer;
  141.   ScaleFactor:real;
  142.   OneToOne:boolean;
  143. begin
  144.   CheckForStack;
  145.   CheckForSelection;
  146.   SaveState;
  147.   OldStack:=PicNumber;
  148.   N:=nSlices;
  149.   ScaleFactor:=GetNumber('Scale factor(0.05..25):',1.0);
  150.   OneToOne:=ScaleFactor=1.0;
  151.   NewWidth:=round(RoiWidth*ScaleFactor);
  152.   if odd(NewWidth) then begin
  153.     NewWidth:=NewWidth-1;
  154.     ScaleFactor:=NewWidth/RoiWidth;
  155.   end;
  156.   SetNewSize(RoiWidth*ScaleFactor,RoiHeight*ScaleFactor);
  157.   MakeNewStack('Stack');
  158.   NewStack:=PicNumber;
  159.   if not OneToOne then begin
  160.     if fast 
  161.       then SetScaling('Nearest; Create New Window')
  162.       else SetScaling('Bilinear; Create New Window');
  163.   end;
  164.   SelectPic(OldStack);
  165.   for i:= 1 to N do begin
  166.     SelectSlice(1);
  167.     if OneToOne and (angle=0.0) then Duplicate('Temp')
  168.       else ScaleAndRotate(ScaleFactor,ScaleFactor,angle);
  169.     SelectAll;
  170.     Copy;
  171.     SelectPic(NewStack);
  172.     if i<>1 then AddSlice;
  173.     Paste;
  174.     SelectPic(nPics);
  175.     Dispose; {Temp}
  176.     SelectPic(OldStack);
  177.     DeleteSlice;
  178.   end;
  179.   Dispose; {OldStack}
  180.   RestoreState;
  181. end;
  182.  
  183. macro 'Crop and Scale-Fast…';   begin CropAndScale(true, 0); end;
  184. macro 'Crop and Scale-Smooth…'; begin CropAndScale(false, 0); end;
  185.  
  186. procedure Rotate(left:boolean);
  187. var
  188.   i,OldStack,NewStack:integer;
  189.   RoiLeft,RoiTop,RoiWidth,RoiHeight:integer;
  190.   N,NewWidth:integer;
  191.   ScaleFactor,SliceSpacing:real;
  192.   OneToOne:boolean;
  193. begin
  194.   CheckForStack;
  195.   SelectAll;
  196.   GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight);
  197.   OldStack:=PicNumber;
  198.   SliceSpacing:=GetSliceSpacing;
  199.   N:=nSlices;
  200.   SetNewSize(RoiHeight,RoiWidth);
  201.   MakeNewStack('Stack');
  202.   if SliceSpacing>0 then SetSliceSpacing(SliceSpacing);
  203.   NewStack:=PicNumber;
  204.   SelectPic(OldStack);
  205.   for i:= 1 to N do begin
  206.     SelectSlice(1);
  207.     if left
  208.       then RotateLeft(true)
  209.       else RotateRight(true);
  210.     SelectAll;
  211.     Copy;
  212.     SelectPic(NewStack);
  213.     if i<>1 then AddSlice;
  214.     Paste;
  215.     ChoosePic(nPics);
  216.     Dispose;
  217.     SelectPic(OldStack);
  218.     DeleteSlice;
  219.   end;
  220.   Dispose;
  221. end;
  222.  
  223.  
  224. macro 'Rotate Left';  begin rotate(true) end;
  225. macro 'Rotate Right'; begin rotate(false) end;
  226.  
  227.  
  228. macro 'Rotate…';
  229. var
  230.   angle:real;
  231. begin
  232.   angle:=GetNumber('Angle(-180.0°..180.0°):',45.0);
  233.   CropAndScale(false, angle);
  234. end;
  235.  
  236.  
  237. macro 'Invert';
  238. var
  239.   i:integer;
  240. begin
  241.   CheckForStack;
  242.   for i:= 1 to nSlices do begin
  243.     SelectSlice(i);
  244.     Invert;
  245.   end;
  246. end;
  247.  
  248.  
  249. procedure flip(vertical:boolean);
  250. var
  251.   i:integer;
  252.   SliceSpacing:real;
  253. begin
  254.   CheckForStack;
  255.   for i:= 1 to nSlices do begin
  256.     SelectSlice(i);
  257.     if vertical
  258.       then FlipVertical
  259.       else FlipHorizontal;
  260.   end;
  261. end;
  262.  
  263. macro 'Flip Vertical';   begin flip(true) end;
  264. macro 'Flip Horizontal'; begin flip(false) end;
  265.  
  266.  
  267. macro 'Delete Even Slices';
  268. var
  269.   n:integer;
  270. begin
  271.   CheckForStack;
  272.   SelectSlice(2);
  273.   repeat
  274.     DeleteSlice;
  275.     n:=SliceNumber;
  276.     n:=n+2;
  277.     if n>nSlices then exit;
  278.     SelectSlice(n);
  279.    until false;
  280. end;
  281.  
  282.  
  283. macro 'Replicate Slices…';
  284. var
  285.   n,i,RepFactor:integer;
  286. begin
  287.   CheckForStack;
  288.   RepFactor:=GetNumber('Replication factor(2,3,4,5,etc):',2);
  289.   n:=nSlices;
  290.   repeat
  291.     SelectSlice(n);
  292.     SelectAll;
  293.     Copy;
  294.     for i:=2 to RepFactor do begin
  295.       AddSlice;
  296.       Paste;
  297.     end;
  298.     n:=n-1;
  299.    until n=0;
  300.    KillRoi;
  301. end;
  302.  
  303.  
  304. macro 'Merge Two Stacks';
  305. {
  306. Combines two stacks(w1xh1xd1 and w2xh2xd2) to create a new
  307. w1+w2 x max(h1,h2) x max(d1,d2) stack. For example, a 256x256x40
  308. and a 256x256x30 stack would be combined into one 512x256x40 stack.
  309. }
  310. var
  311.   i,w1,w2,w3,h1,h2,h3,d1,d2,d3:integer;
  312. begin
  313.   SaveState;
  314.   if nPics<>2 then begin
  315.     PutMessage('This macro operates on exactly two stacks.');
  316.     exit;
  317.   end;
  318.   SelectPic(1);
  319.   GetPicSize(w1,h1);
  320.   d1:=nSlices;
  321.   SelectPic(2);
  322.   GetPicSize(w2,h2);
  323.   d2:=nSlices;
  324.   if d1>=d2
  325.     then d3:=d1
  326.     else d3:=d2;
  327.   if d3=0 then begin
  328.     PutMessage('Both images must be stacks.');
  329.     exit;
  330.   end;
  331.   w3:=w1+w2;
  332.   if h1>=h2
  333.     then h3:=h1
  334.     else h3:=h2;
  335.   SetNewSize(w3,h3);
  336.   MakeNewStack('Merged');
  337.   for i:=1 to d3 do begin
  338.     SelectPic(1);
  339.     SelectSlice(1);
  340.     SelectAll;
  341.     Copy;
  342.     DeleteSlice;
  343.     SelectPic(3);
  344.     MakeRoi(0,0,w1,h1);
  345.     Paste;
  346.     SelectPic(2);
  347.     SelectSlice(1);
  348.     SelectAll;
  349.     Copy;
  350.     DeleteSlice;
  351.     SelectPic(3);
  352.     MakeRoi(w1,0,w2,h2);
  353.     Paste;
  354.     if i<d3 then AddSlice;
  355.   end;
  356.   SelectPic(1);
  357.   Dispose;
  358.   SelectPic(1);
  359.   Dispose;
  360.   RestoreState;
  361. end;
  362.  
  363.  
  364. macro 'Average Two Stacks';
  365. {Creates the frame by frame average of two stacks.}
  366. var
  367.   i,w1,w2,w3,h1,h2,h3,d1,d2,d3,avg:integer;
  368. begin
  369.   RequiresVersion(1.53);
  370.   SaveState;
  371.   if nPics<>2 then begin
  372.     PutMessage('This macro operates on exactly two stacks.');
  373.     exit;
  374.   end;
  375.   SelectPic(1);
  376.   KillRoi;
  377.   GetPicSize(w1,h1);
  378.   d1:=nSlices;
  379.   SelectPic(2);
  380.   KillRoi;
  381.   GetPicSize(w2,h2);
  382.   d2:=nSlices;
  383.   if d1>=d2
  384.     then d3:=d1
  385.     else d3:=d2;
  386.   if (w1<>w2) or (h1<>h2) or (d1<>d2) or (d1=0)  then begin
  387.     PutMessage('This macro requires two stacks that are the same size.');
  388.     exit;
  389.   end;
  390.   SetNewSize(w1,h1);
  391.   MakeNewStack('Average');
  392.   avg:=PicNumber;
  393.   for i:=1 to d1 do begin
  394.     SelectPic(1);
  395.     SelectSlice(i);
  396.     SelectPic(2);
  397.     SelectSlice(i);
  398.    ImageMath('Add', 1, 2, 0.5, 0, 'Temp');
  399.     SelectAll;
  400.     Copy;
  401.     dispose;
  402.     SelectPic(avg);
  403.     if i<>1 then AddSlice;
  404.     paste;
  405.    end;
  406.   RestoreState;
  407. end;
  408.  
  409.  
  410. macro 'Concatenate Two Stacks';
  411. var
  412.   i,w1,w2,h1,h2,d1,d2:integer;
  413. begin
  414.   RequiresVersion(1.61);
  415.   SaveState;
  416.   if nPics<>2 then
  417.     exit('Exactly two stacks required.');
  418.   SelectPic(1);
  419.   GetPicSize(w1,h1);
  420.   d1:=nSlices;
  421.   SelectPic(2);
  422.   GetPicSize(w2,h2);
  423.   d2:=nSlices;
  424.   if (d1=0) or (d2=0) or (w1<>w2) or (h1<>h2) then
  425.     exit('Two stacks with the same dimensions required.');
  426.         SelectPic(1);
  427.   SelectSlice(d1);
  428.   for i:=1 to d2 do begin
  429.     ChoosePic(2);
  430.     SelectSlice(1);
  431.     SelectAll;
  432.     Copy;
  433.     DeleteSlice;
  434.     ChoosePic(1);
  435.     AddSlice;
  436.     MakeRoi(0,0,w1,h1);
  437.     Paste;
  438.   end;
  439.   SelectPic(2);
  440.   Dispose;
  441.   RestoreState;
  442. end;
  443.  
  444.  
  445. macro '(-' begin end;
  446.  
  447.  
  448. macro 'Save Slices as files…';
  449. {
  450. This macro saves the slices in a stack as individual TIFF or PICT files using
  451. names of the form needed by Apple's Convert to [QuickTime]Movie utility.
  452. To specify the file type, checked either TIFF or PICT in the SaveAs dialog
  453. box, which should only appear once.
  454. }
  455. var
  456.   i,stack:integer;
  457. begin
  458.   CheckForStack;
  459.   stack:=PidNumber;
  460.   for i:= 1 to nSlices do begin
  461.     SelectPic(stack);
  462.     SelectSlice(i);
  463.     Duplicate('Frame.',i:3);
  464.     SaveAs;
  465.     {Export;}
  466.     Dispose;
  467.   end;
  468. end;
  469.  
  470.  
  471. macro 'Windows to Stack';
  472. {Unlike the menu command of the same name, the windows do not}
  473. {all need to be the same size.}
  474. var
  475.   i,width,height,MinWidth,MinHeight,n,stack:integer;
  476.   isStack:boolean;
  477. begin
  478.   if nPics<=1 then begin
  479.     PutMessage('At least two images must be open.');
  480.     exit;
  481.   end;
  482.   MinWidth:=9999;
  483.   MinHeight:=9999;
  484.   isStack:=false;
  485.   for i:=1 to nPics do begin
  486.     SelectPic(i);
  487.     GetPicSize(width,height);
  488.     if width<MinWidth then MinWidth:=width;
  489.     if height<MinHeight then MinHeight:=height;
  490.     isStack:=isStack or (nSlices>0);
  491.   end;
  492.   if isStack then begin
  493.     PutMessage('This macro does not work with stacks.');
  494.     exit;
  495.   end;
  496.   if odd(MinWidth) then MinWidth:=MinWidth-1;
  497.   n:=nPics;
  498.   SaveState;
  499.   SetNewSize(MinWidth,MinHeight);
  500.   MakeNewStack('Stack');
  501.   stack:=nPics;
  502.   for i:=1 to n do begin
  503.     SelectPic(1);
  504.     MakeRoi(0,0,MinWidth,MinHeight);
  505.     copy;
  506.     Dispose;
  507.     SelectPic(nPics);
  508.     paste;
  509.     if i<>n then AddSlice;
  510.   end;
  511.   KillRoi;
  512.   RestoreState;
  513. end;
  514.  
  515.  
  516. Macro 'Stack to Windows'
  517. var
  518.   mystack,i:integer
  519.   width,height:integer;
  520. begin
  521.   SaveState;
  522.   CheckForStack;
  523.   GetPicSize(width,height);
  524.   SetNewSize(width,height);
  525.   mystack := picnumber;
  526.   for i:=1 to nslices do begin
  527.     SelectSlice(i);
  528.     SelectAll;
  529.     copy;
  530.     MakeNewWindow(i);
  531.     paste;
  532.     SelectPic(myStack);
  533.   end;
  534.   KillRoi;
  535.   RestoreState;
  536. end;
  537.  
  538.  
  539. macro 'Make Cone';
  540. var
  541.   i,size,margin,MaxRadius,r,r2,center,RodLength,color:integer;
  542. begin
  543.   size:=64;
  544.   margin:=5;
  545.   color:=100;
  546.   SaveState;
  547.   SetBackgroundColor(255); {Black}
  548.   SetNewSize(size,size);
  549.   MakeNewStack('Cone');
  550.   for i:=1 to margin do AddSlice;
  551.   MaxRadius:=(size-2*margin)/2;
  552.   center:=size div 2;
  553.   RodLength:=size-2*margin-1;
  554.   for i:=1 to RodLength do begin
  555.     AddSlice;
  556.     r:=MaxRadius*(i/RodLength);
  557.     MakeOvalRoi(center-r,center-r,r*2,r*2);
  558.     SetForegroundColor(color);
  559.     Fill;
  560.     if (i>RodLength/2) and (i<(RodLength-margin)) then begin
  561.       r2:=MaxRadius/6;
  562.       MakeOvalRoi(center-2.125*r2,center-1.3*r2,r2*2,r2*2);
  563.       SetForegroundColor(color-25);
  564.       Fill;
  565.       MakeOvalRoi(center+0.625*r2,center-0.7*r2,r2*2,r2*2);
  566.       SetForegroundColor(color+25);
  567.       Fill;
  568.     end;
  569.   end;
  570.   for i:=1 to margin do AddSlice;
  571.   KillRoi;
  572.   RestoreState;
  573. end;
  574.  
  575.  
  576. procedure DoReslicing(horizontal:boolean);
  577. var
  578.   stack1,stack2,width,height:integer;
  579.   RoiLeft,RoiTop,RoiWidth,RoiHeight,max:integer;
  580.   InputSpacing,OutputSpacing,loc:real;
  581.   FirstTime:boolean;
  582. begin
  583.   RequiresVersion(1.45);
  584.   CheckForStack;
  585.   CheckForSelection;
  586.   SaveState;
  587.   SetBackground(0);
  588.   SetBackground(255);
  589.   stack1:=PicNumber;
  590.   InputSpacing:=GetSliceSpacing;
  591.   if InputSpacing<=0 then InputSpacing:=1;
  592.   InputSpacing:=GetNumber('Input Slice Spacing(Pixels):',InputSpacing);
  593.   SetSliceSpacing(InputSpacing);
  594.   OutputSpacing:=InputSpacing;
  595.   OutputSpacing:=GetNumber('Output Slice Spacing (Pixels):', OutputSpacing);
  596.   FirstTime:=true;
  597.   GetRoi(RoiLeft,RoiTop,RoiWidth,RoiHeight);
  598.   if horizontal then begin
  599.     loc:=RoiTop+OutputSpacing;
  600.     max:=RoiTop+RoiHeight;
  601.   end else begin
  602.     loc:=RoiLeft+OutputSpacing;
  603.     max:=RoiLeft+RoiWidth;
  604.   end;
  605.   while loc<max do begin
  606.     ChoosePic(stack1);
  607.     if horizontal
  608.       then MakeLineRoi(RoiLeft,loc,RoiLeft+RoiWidth,loc)
  609.       else MakeLineRoi(loc,RoiTop,loc,RoiTop+RoiHeight);
  610.     Reslice;
  611.     SelectAll;
  612.     Copy;
  613.     GetPicSize(width,height);
  614.     Dispose;
  615.     if FirstTime then begin
  616.       SetNewSize(width,height);
  617.       MakeNewStack(OutputSpacing:1:2);
  618.       SetSliceSpacing(OutputSpacing);
  619.       stack2:=PicNumber;
  620.     end;
  621.     ChoosePic(stack2);
  622.     if not FirstTime then AddSlice;
  623.     Paste;
  624.     loc:=loc+OutputSpacing;
  625.     FirstTime:=false;
  626.   end;
  627.   SelectPic(stack1);
  628.   KillRoi;
  629.   SelectPic(stack2);
  630.   KillRoi;
  631.   RestoreState;
  632. end;
  633.  
  634.  
  635. macro 'Reslice Horizontally…'; begin DoReslicing(true) end;
  636. macro 'Reslice Vertically…';   begin DoReslicing(false) end;
  637.  
  638.